home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / checkbox / reactor.py < prev    next >
Encoding:
Python Source  |  2009-04-27  |  3.7 KB  |  123 lines

  1. #
  2. # This file is part of Checkbox.
  3. #
  4. # Copyright 2008 Canonical Ltd.
  5. #
  6. # Checkbox is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # Checkbox is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with Checkbox.  If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. import re
  20. import logging
  21.  
  22. from checkbox.lib.log import format_object
  23.  
  24.  
  25. class EventID(object):
  26.  
  27.     def __init__(self, event_type, pair):
  28.         self._event_type = event_type
  29.         self._pair = pair
  30.  
  31.  
  32. class StopException(Exception):
  33.  
  34.     pass
  35.  
  36.  
  37. class StopAllException(Exception):
  38.  
  39.     pass
  40.  
  41.  
  42. class Reactor(object):
  43.  
  44.     def __init__(self):
  45.         self._event_handlers = {}
  46.         self._event_stack = []
  47.  
  48.     def call_on(self, event_type, handler, priority=0):
  49.         pair = (handler, priority)
  50.  
  51.         logging.debug("Calling %s on %s.", format_object(handler), event_type)
  52.         handlers = self._event_handlers.setdefault(event_type, [])
  53.         handlers.append(pair)
  54.  
  55.         return EventID(event_type, pair)
  56.  
  57.     def fire(self, event_type, *args, **kwargs):
  58.         logging.debug("Started firing %s.", event_type)
  59.  
  60.         if event_type in self._event_stack:
  61.             raise StopAllException, "Loop detected for event type: %s." \
  62.                 % event_type
  63.  
  64.         self._event_stack.append(event_type)
  65.  
  66.         results = []
  67.         handlers = []
  68.         for key, value in self._event_handlers.items():
  69.             if re.match("^%s$" % key, event_type):
  70.                 handlers.extend(value)
  71.  
  72.         handlers = sorted(handlers, key=lambda pair: pair[1])
  73.         if not handlers:
  74.             logging.debug("No handlers found for event type: %s", event_type)
  75.  
  76.         for handler, priority in handlers:
  77.             try:
  78.                 logging.debug("Calling %s for %s with priority %d.",
  79.                               format_object(handler), event_type, priority)
  80.                 results.append(handler(*args, **kwargs))
  81.             except StopException:
  82.                 break
  83.             except StopAllException:
  84.                 raise
  85.             except KeyboardInterrupt:
  86.                 logging.exception("Keyboard interrupt while running event "
  87.                                   "handler %s for event type %r with "
  88.                                   "args %r %r.", format_object(handler),
  89.                                   event_type, args, kwargs)
  90.                 self.stop_all()
  91.             except:
  92.                 logging.exception("Error running event handler %s for "
  93.                                   "event type %r with args %r %r.",
  94.                                   format_object(handler), event_type,
  95.                                   args, kwargs)
  96.  
  97.         self._event_stack.pop(-1)
  98.  
  99.         logging.debug("Finished firing %s.", event_type)
  100.         return results
  101.  
  102.     def cancel_call(self, id):
  103.         if type(id) is EventID:
  104.             self._event_handlers[id._event_type].remove(id._pair)
  105.         else:
  106.             raise Exception, "EventID instance expected, received %r" % id
  107.  
  108.     def cancel_all_calls(self, event_type):
  109.         del self._event_handlers[event_type]
  110.  
  111.     def run(self):
  112.         try:
  113.             self.fire("run")
  114.         except StopAllException, e:
  115.             logging.critical(e)
  116.         self.fire("stop")
  117.  
  118.     def stop(self):
  119.         raise StopException
  120.  
  121.     def stop_all(self):
  122.         raise StopAllException
  123.